﻿// Copyright (c) ZhangPeihang. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using LaserMark.ModbusTCP.Abstraction;
using LaserMark.ModbusTCP.Config;
using Microsoft.Extensions.Options;
using System.Net.Sockets;

namespace LaserMark.ModbusTCP
{
    public class ModBusMaster : IMaster, IDisposable
    {
        private TcpClient? _tcpClient;

        private string? _ip;

        private int _port;

        private int _retrycount;

        public bool IsConnected
        {
            get
            {
                if (_tcpClient != null)
                {
                    return _tcpClient.Connected;
                }
                else
                {
                    return false;
                }
            }
        }

        public ModBusMaster(IOptions<ModBusOption> options)
        {
            _ip = options.Value.Address;
            _port = options.Value.Port;
            _tcpClient = new TcpClient();
        }

        public async Task<string> ConnectAsync()
        {
            if (_tcpClient != null && !_tcpClient.Connected)
            {
                try
                {
                    await _tcpClient.ConnectAsync(_ip!, _port);
                    return "";
                }
                catch (SocketException ex)
                {
                    return ex.Message;
                }
            }
            else
            {
                return "";
            }
        }

        public Task<double> RedKeepRegister(short reg, short count)
        {

            // 00 00 00 00 00 06 01 04 00 00 00 01
            List<byte> sendCommond = new List<byte>();
            sendCommond.AddRange(new byte[] { 0x00, 0x00 });
            sendCommond.AddRange(new byte[] { 0x00, 0x00 });
            sendCommond.AddRange(new byte[] { 0x00, 0x06 });
            sendCommond.Add(0x01);
            sendCommond.Add(0x04);
            sendCommond.Add(0x00);
            sendCommond.Add(0x00);
            sendCommond.Add(0x00);
            sendCommond.Add(0x01);
            if (_tcpClient != null && _tcpClient.Connected)
            {
                try
                {
                    _tcpClient.Client.Send(sendCommond.ToArray());

                    var buffer = new byte[256];
                    var lenght = _tcpClient.Client.Receive(buffer, SocketFlags.None);
                    var data = new byte[lenght];
                    Array.Copy(buffer, data, lenght);
                    var str = data.ToArray()[9..data.Length];
                    var hex = Convert.ToHexString(str);
                    return Task.FromResult((Convert.ToInt32(hex, 16) * 15255) / (double)100000000);
                }
                catch (Exception ex)
                {
                }
            }

            return Task.FromResult(0.0);
        }

        public Task DisConnect()
        {
            _tcpClient?.Dispose();
            return Task.CompletedTask;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            _tcpClient?.Dispose();
        }
    }
}
